package pkg

import (
	"context"
	"errors"
	"fmt"
	"log"
	"regexp"

	"github.com/go-redis/redis/v8"
	goversion "github.com/hashicorp/go-version"
)

const (
	Addr     = "localhost:6379"
	Password = "123456"
	DB       = 0
)

const (
	RedisMinVersion = "4.0.0"
)

type Client struct {
	Conn *redis.Client
}

func NewClient(conn *redis.Client) *Client {
	return &Client{Conn: conn}
}

func ConnectRedis() *redis.Client {
	conn := redis.NewClient(&redis.Options{
		Addr:     Addr,
		Password: Password,
		DB:       DB,
	})
	ctx := context.Background()

	if _, err := conn.Ping(ctx).Result(); err != nil {
		log.Fatalf("Connect to redis client failed, err: %v\n", err)
	}
	if _, err := CheckServerVersion(conn); err != nil {
		log.Fatalf("Check redis version failed, err: %v\n", err)
	}
	return conn
}

func CheckServerVersion(conn *redis.Client) (version string, err error) {
	ctx := context.Background()
	cmd := conn.Info(ctx, "server")
	serverInfo := cmd.Val()
	if len(serverInfo) == 0 {
		err = errors.New(fmt.Sprintf("Get server info failed, err: %v", cmd.Err()))
		return
	}
	r := regexp.MustCompile(`redis_version:((\d+\.)+\d+)`)
	matchSlice := r.FindStringSubmatch(serverInfo)
	if len(matchSlice) < 2 {
		err = errors.New("regexp not match redis version")
		return
	}
	version = matchSlice[1]
	return CheckVersion(version, RedisMinVersion)
}

func CheckVersion(serverVersion string, minVersion string) (version string, err error) {
	v1, err := goversion.NewVersion(serverVersion)
	if err != nil {
		err = errors.New(fmt.Sprintf("New version failed from string: %s, err: %v", v1, err))
		return
	}
	v2, err := goversion.NewVersion(minVersion)
	if err != nil {
		err = errors.New(fmt.Sprintf("New version failed from string: %s, err: %v", v2, err))
		return
	}

	if v1.LessThan(v2) {
		err = errors.New(fmt.Sprintf("Server version %s does not meet minimum version requirements: %s", serverVersion, minVersion))
		return
	}

	version = serverVersion
	return
}
